package controllers

import (
	"strings"

	"cvevulner/errcode"
	"cvevulner/models"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
)

// Operations about Packages
type PackagesController struct {
	beego.Controller
}

func (c *PackagesController) RetData(resp map[string]interface{}) {
	c.Data["json"] = resp
	c.ServeJSON()
}

type PackagesInfoController struct {
	beego.Controller
}

func (c *PackagesInfoController) RetData(resp map[string]interface{}) {
	c.Data["json"] = resp
	c.ServeJSON()
}

type PackageData struct {
	Id                int64  `json:"id"`
	Name              string `json:"name"`
	Version           string `json:"version"`
	Release           string `json:"release"`
	OriginUrl         string `json:"url"`
	CpeName           string `json:"cpeName"`
	ReleaseTime       string `json:"releaseTime"`
	LatestVersion     string `json:"latestVersion"`
	LatestVersionTime string `json:"latestVersionTime"`
	Repo              string `json:"repo"`
	PackageId         int64  `json:"package_id"`
}

type Provide struct {
	Name       string   `json:"name"`
	Requiredby []string `json:"requiredby"`
}

type Require struct {
	Name       string   `json:"name"`
	Providedby []string `json:"providedby"`
}

type SubPack struct {
	Name     string    `json:"name"`
	Provides []Provide `json:"provides"`
	Requires []Require `json:"requires"`
}

type PackageInfoData struct {
	PkgName       string    `json:"pkgName"`
	Version       string    `json:"version"`
	Release       string    `json:"release"`
	OriginUrl     string    `json:"url"`
	GiteeUrl      string    `json:"giteeUrl"`
	Summary       string    `json:"summary"`
	Description   string    `json:"description"`
	BuildRequired []string  `json:"buildRequired"`
	Subpack       []SubPack `json:"subpack"`
}

// @Title Get packages
// @Description get packages
// @Param	pageNum		pageSize 	int	true
// @Success 200 {object} models.package
// @Failure 403 :pageNum is err
// @router / [get]
func (u *PackagesController) Get() {
	req := u.Ctx.Request
	addr := req.RemoteAddr
	logs.Info("Method: ", req.Method, "Client request ip address: ", addr,
		", Header: ", req.Header, ", body: ", req.Body)
	resp := make(map[string]interface{})
	var pd []PackageData
	resp["errno"] = errcode.RecodeUnknowErr
	resp["errmsg"] = errcode.RecodeText(errcode.RecodeUnknowErr)
	resp["body"] = []PackageData{}
	resp["totalCount"] = 0
	resp["totalPage"] = 0
	//defer u.RetData(resp)
	var iw models.IpWhite
	if addr != "" {
		addrIp := strings.Split(addr, ":")
		err := models.GetIpWhite(addrIp[0], &iw)
		if err != nil {
			resp["errno"] = errcode.RecodeIpErr
			resp["errmsg"] = errcode.RecodeText(errcode.RecodeIpErr)
			u.RetData(resp)
			return
		}
	} else {
		resp["errno"] = errcode.RecodeIpErr
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeIpErr)
		u.RetData(resp)
		return
	}
	token := u.GetString("token")
	if token == "" {
		resp["errno"] = errcode.RecodeSessionErr
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeSessionErr)
		u.RetData(resp)
		return
	} else {
		ok := models.CheckToken(token)
		if !ok {
			resp["errno"] = errcode.RecodeRoleErr
			resp["errmsg"] = errcode.RecodeText(errcode.RecodeRoleErr)
			u.RetData(resp)
			return
		}
	}
	PageNum, err := u.GetInt64("pageNum")
	if err != nil {
		logs.Error("pageNum, err: ", err)
		resp["errno"] = errcode.RecodeParamErr
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeParamErr)
		u.RetData(resp)
		return
	}
	PageSize, err := u.GetInt64("pageSize")
	if err != nil {
		logs.Error("PageSize, err: ", err)
		resp["errno"] = errcode.RecodeParamErr
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeParamErr)
		u.RetData(resp)
		return
	}
	QueryPkgName := u.GetString("queryPkgName")
	if QueryPkgName != "" {
		logs.Info("Query data: ", QueryPkgName, ", Information about the package")
	}

	organizateId, err := u.GetInt64("organizateId", 1)
	if err != nil {
		organizateId = 1
	}

	var totalNum int64
	if organizateId == 1 {
		totalNum = models.GetPackageNum(QueryPkgName)
	} else if organizateId == 2 {
		totalNum = models.GetPackageNumForGauss(QueryPkgName)
	} else if organizateId == 3 {
		totalNum = models.GetPackageNumForMindSpore(QueryPkgName)
	} else if organizateId == 4 {
		totalNum = models.GetPackageNumForOpenLook(QueryPkgName)
	}
	if totalNum > 0 {
		if PageSize >= totalNum {
			resp["totalPage"] = 1
		} else {
			if totalNum%PageSize == 0 {
				resp["totalPage"] = totalNum / PageSize
			} else {
				totalPage := totalNum / PageSize
				totalPage += 1
				resp["totalPage"] = totalPage
			}
		}
		resp["totalCount"] = totalNum
		if organizateId == 1 {
			ge, num, err := models.GetPackageList(PageSize, PageNum, QueryPkgName)
			if num > 0 && err == nil {
				for _, g := range ge {
					var pg PackageData
					pg.Id = g.GitId
					pg.Release = g.Release
					pg.Version = g.Version
					pg.CpeName = g.CpePackName
					pg.LatestVersion = g.LatestVersion
					pg.LatestVersionTime = g.LatestVersionTime
					pg.Name = g.PackageName
					pg.OriginUrl = g.OriginUrl
					pg.ReleaseTime = g.ReleaseTime
					pg.PackageId = g.PackageId
					pd = append(pd, pg)
				}
				resp["body"] = pd
				resp["errno"] = errcode.RecodeOk
				resp["errmsg"] = errcode.RecodeText(errcode.RecodeOk)
				u.RetData(resp)
			}
		} else if organizateId == 2 {
			ge, num, err := models.GetPackageListForGauss(PageSize, PageNum, QueryPkgName)
			if num > 0 && err == nil {
				for _, g := range ge {
					var pg PackageData
					pg.Id = g.Id
					pg.Version = g.Version
					pg.CpeName = g.CpeName
					pg.Name = g.PackageName
					pg.OriginUrl = g.OriginUrl
					pg.Repo = g.Repo
					pd = append(pd, pg)
				}
				resp["body"] = pd
				resp["errno"] = errcode.RecodeOk
				resp["errmsg"] = errcode.RecodeText(errcode.RecodeOk)
				u.RetData(resp)
			}
		} else if organizateId == 3 {
			ge, num, err := models.GetPackageListForMindSpore(PageSize, PageNum, QueryPkgName)
			if num > 0 && err == nil {
				for _, g := range ge {
					var pg PackageData
					pg.Id = g.Id
					pg.Version = g.Version
					pg.CpeName = g.CpeName
					pg.Name = g.PackageName
					pg.OriginUrl = g.OriginUrl
					pg.Repo = g.Repo
					pd = append(pd, pg)
				}
				resp["body"] = pd
				resp["errno"] = errcode.RecodeOk
				resp["errmsg"] = errcode.RecodeText(errcode.RecodeOk)
				u.RetData(resp)
			}
		} else if organizateId == 4 {
			ge, num, err := models.GetPackageListForOpenLook(PageSize, PageNum, QueryPkgName)
			if num > 0 && err == nil {
				for _, g := range ge {
					var pg PackageData
					pg.Id = g.Id
					pg.Version = g.Version
					pg.CpeName = g.CpeName
					pg.Name = g.PackageName
					pg.OriginUrl = g.OriginUrl
					pg.Repo = g.Repo
					pd = append(pd, pg)
				}
				resp["body"] = pd
				resp["errno"] = errcode.RecodeOk
				resp["errmsg"] = errcode.RecodeText(errcode.RecodeOk)
				u.RetData(resp)
			}
		}
	} else {
		resp["errno"] = errcode.RecodeNodata
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeNodata)
		u.RetData(resp)
		return
	}
}

// @Title Get packagesinfo
// @Description get packagesinfo
// @Param	pkgName		token 	string	true
// @Success 200 {object} models.package
// @Failure 403 :pkgName is err
// @router / [get]
func (u *PackagesInfoController) Get() {
	req := u.Ctx.Request
	addr := req.RemoteAddr
	logs.Info("Method: ", req.Method, "Client request ip address: ", addr,
		", Header: ", req.Header, ", body: ", req.Body)
	resp := make(map[string]interface{})
	var pd PackageInfoData
	resp["errno"] = errcode.RecodeUnknowErr
	resp["errmsg"] = errcode.RecodeText(errcode.RecodeUnknowErr)
	resp["body"] = PackageInfoData{}
	//defer u.RetData(resp)
	var iw models.IpWhite
	if addr != "" {
		addrIp := strings.Split(addr, ":")
		err := models.GetIpWhite(addrIp[0], &iw)
		if err != nil {
			resp["errno"] = errcode.RecodeIpErr
			resp["errmsg"] = errcode.RecodeText(errcode.RecodeIpErr)
			u.RetData(resp)
			return
		}
	} else {
		resp["errno"] = errcode.RecodeIpErr
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeIpErr)
		u.RetData(resp)
		return
	}
	token := u.GetString("token")
	if token == "" {
		resp["errno"] = errcode.RecodeSessionErr
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeSessionErr)
		u.RetData(resp)
		return
	} else {
		ok := models.CheckToken(token)
		if !ok {
			resp["errno"] = errcode.RecodeRoleErr
			resp["errmsg"] = errcode.RecodeText(errcode.RecodeRoleErr)
			u.RetData(resp)
			return
		}
	}
	pkgName := u.GetString("pkgName")
	if pkgName == "" {
		logs.Error("pkgName, Parameter error")
		resp["errno"] = errcode.RecodeParamErr
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeParamErr)
		u.RetData(resp)
		return
	}
	version := u.GetString("version")
	if version == "" {
		logs.Error("version, Parameter error")
		resp["errno"] = errcode.RecodeParamErr
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeParamErr)
		u.RetData(resp)
		return
	}
	var gi models.GitPackageInfo
	err := models.GetPackageInfo(pkgName, version, &gi)
	if err != nil {
		resp["errno"] = errcode.RecodeNodata
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeNodata)
		u.RetData(resp)
		return
	}
	pd.OriginUrl = gi.OriginUrl
	pd.Version = gi.Version
	pd.PkgName = gi.PackageName
	pd.Release = gi.Release
	pd.Description = gi.Decription
	pd.GiteeUrl = gi.GitUrl
	pd.Summary = gi.Summary
	if gi.BuildRequired != "" {
		buildRequired := strings.Split(gi.BuildRequired, ",")
		pd.BuildRequired = buildRequired
	} else {
		pd.BuildRequired = []string{}
	}
	gs, num, err := models.GetSubPackage(gi.DetailId)
	if num > 0 && err == nil {
		for _, gg := range gs {
			var sp SubPack
			sp.Name = gg.SubPackName
			gsp, numx, errx := models.GetSubPackProvide(gg.SubId)
			if numx > 0 && errx == nil {
				for _, gps := range gsp {
					var ssp Provide
					ssp.Name = gps.ProvideName
					gspr, numxx, errxx := models.GetSubPackrequiredby(gps.ProvideId)
					if numxx > 0 && errxx == nil {
						for _, grq := range gspr {
							ssp.Requiredby = append(ssp.Requiredby, grq.Requiredby)
						}
					} else {
						ssp.Requiredby = []string{}
					}
					sp.Provides = append(sp.Provides, ssp)
				}
			} else {
				sp.Provides = []Provide{}
			}
			gpre, numm, err := models.GetSubPackRequire(gg.SubId)
			if numm > 0 && err == nil {
				for _, ges := range gpre {
					var rssp Require
					rssp.Name = ges.RequireName
					if ges.Providedby != "" {
						rssp.Providedby = strings.Split(ges.Providedby, ",")
					} else {
						rssp.Providedby = []string{}
					}
					sp.Requires = append(sp.Requires, rssp)
				}
			} else {
				sp.Requires = []Require{}
			}
			pd.Subpack = append(pd.Subpack, sp)
		}

	} else {
		pd.Subpack = []SubPack{}
	}
	resp["errno"] = errcode.RecodeOk
	resp["errmsg"] = errcode.RecodeText(errcode.RecodeOk)
	resp["body"] = pd
	u.RetData(resp)
	return
}
